import importlib
import os
from dotenv import load_dotenv
from flask import Flask
from app.api import APP_BLUEPRINT_MAP
from app.model import *


def register_blueprint(app):
    app_blueprints = APP_BLUEPRINT_MAP

    if app_blueprints is None:
        raise KeyError("APP_TYPE 不存在于 APP_BLUEPRINT_MAP 中")

    # 由于 flask 蓝图的 Rule 规则是在 register_blueprint 时添加，所以蓝图在注册时必须先加载
    for path, url_path, blueprint, prefix in app_blueprints:
        for root, dirs, files in os.walk(path.replace(".", "/")):
            modules = ['.'.join([root, fn]).rsplit('.', 1)[0] for fn in [f for f in files if f.endswith('py')]]
            for module_ in modules:
                module = module_.replace("\\", ".")
                __import__(module.replace("/", "."))

        if url_path:
            c = importlib.__import__(url_path, fromlist=["api"])
            crust_api = getattr(c, "api", None)
            crust_api.prefix = prefix
            crust_api.init_app(app)


def register_db(app):
    from app.serve.wtrees.db import db
    db.init_app(app)


def register_jwt(app):
    from app.serve.user.auth import jwt
    jwt.init_app(app)


def register_cli(app):
    from app.cli import db_cli
    app.cli.add_command(db_cli)



def apply_cors(app):
    from flask_cors import CORS

    CORS(app)


def load_app_config(app):
    """
    根据指定配置环境自动加载对应环境变量和配置类到app config
    """
    # 根据传入环境加载对应配置
    env = app.config.get("ENV")
    # 读取 .env
    load_dotenv(".{env}.env".format(env=env))
    # 读取配置类
    app.config.from_object(
        "app.config.{env}.{Env}Config".format(env=env, Env=env.capitalize())
    )


def create_app(register_all=True):
    load_dotenv(".flaskenv")
    app = Flask(__name__, static_folder="../assets")
    load_app_config(app)
    if register_all:
        register_blueprint(app)
        register_db(app)
        apply_cors(app)
        register_cli(app)
        register_jwt(app)
    return app
